package com.amkai.aes.webservice.binary.objecthandler.personnel;

import java.io.Serializable;
import java.util.List;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Query;

import com.amkai.aes.aescommon.factory.RADBeanFactory;
import com.amkai.aes.aescommon.service.binary.job.personnel.PrivilegeProcedureJob;
import com.amkai.aes.aescommon.service.result.personnel.PrivilegeProcedureResult;
import com.amkai.aes.generatedbeans.organization.Department;
import com.amkai.aes.generatedbeans.personnel.PrivilegeAndProcedureAssociation;
import com.amkai.aes.generatedbeans.personnel.details.Privilege;
import com.amkai.aes.generatedbeans.procedure.Procedure;
import com.amkai.aes.webservice.binary.JobObjectHandler;
import com.amkai.common.extensions.hibernate.config.SiteManager;
import com.amkai.common.extensions.hibernate.config.manager.SessionManager;

// KKORNEL: AES-14980 - moved from com.amkai.aes.webservice.binary.objecthandler created by cyb
public class PrivilegeProcedureHandler implements JobObjectHandler<PrivilegeProcedureJob, java.io.Serializable, PrivilegeProcedureResult>{

	private static final Log log = LogFactory.getLog(PrivilegeProcedureHandler.class);

	
	@Override
	public PrivilegeProcedureResult process(PrivilegeProcedureJob job,
			Serializable object) throws Exception {
		PrivilegeProcedureResult result = new PrivilegeProcedureResult();
		
		SessionManager manager = SiteManager.Start();
		manager.openSession();
		//manager.openTransaction();
		try{
			int itemCount = 0;
			switch(job.getKind()){
			case ADD :								
				for(Procedure procedure : job.getProcedures()){
					PrivilegeAndProcedureAssociation association = RADBeanFactory.getInstance().createBean(PrivilegeAndProcedureAssociation.class);
					association.setPrivilege(job.getTargetPrivilege());
					association.setProcedure( procedure);
					manager.saveRADInTransaction(association);
					manager.clear();
					itemCount++;
				}
				break;
			case ADD_ALL : 
//				String insert = "INSERT INTO "
//				DP > http://jira.amkai.com:8080/browse/AES-13493
				manager.openTransaction();
				manager.execute("DELETE From PrivilegeAndProcedureAssociation ass WHERE ass.privilege.id = " + job.getTargetPrivilege().getId() ).executeUpdate();
				manager.commitTransaction();
				manager.openTransaction();
				int i = 0;
				for(Long procedure : getProcedures(manager, job.getTargetPrivilege(), job.getModuleDepartment())){
					PrivilegeAndProcedureAssociation association = RADBeanFactory.getInstance().createBean(PrivilegeAndProcedureAssociation.class);
					association.setPrivilege(job.getTargetPrivilege());
					association.setProcedure(manager.get(Procedure.class, procedure));
					manager.saveRAD(association);
					i++;
					if (i == 50){
						manager.flush();
						manager.clear();
						i = 0;
					}
					itemCount++;
 
				}
				manager.commitTransaction();
				break;
			case COPY :	
				for(PrivilegeAndProcedureAssociation association : getAssociations(manager, job.getSourcePrivilege())){
					PrivilegeAndProcedureAssociation copied = getAssociation(manager, job.getTargetPrivilege(), association.getProcedure());
					if(copied == null){
						copied = RADBeanFactory.getInstance().createBean(PrivilegeAndProcedureAssociation.class);
						copied.setPrivilege(job.getTargetPrivilege());
						copied.setProcedure(association.getProcedure());
						manager.saveRADInTransaction(copied);
						manager.clear();
						itemCount++;
					}
				}
				break;
			case REMOVE :
				manager.openTransaction();
				itemCount = manager.execute("DELETE FROM PrivilegeAndProcedureAssociation ass WHERE ass.privilege.id = :pid AND ass.procedure in (:proclist)")
				.setLong("pid",  job.getTargetPrivilege().getId()) 
				.setParameterList( "proclist", job.getProcedures()).executeUpdate();
				manager.commitTransaction();
				break;
			case REMOVE_ALL :
				manager.openTransaction();
				manager.execute("DELETE From PrivilegeAndProcedureAssociation ass WHERE ass.privilege.id = " + job.getTargetPrivilege().getId() ).executeUpdate();
				manager.commitTransaction();
				
				break;
			}
			result.setItemCount(itemCount);
			
		}catch(Exception exception){
			manager.rollbackTransaction();
			log.error("", exception);
			throw exception;
		}finally{
			manager.closeSession();
		}
		return result;
	}
	
	private PrivilegeAndProcedureAssociation getAssociation(SessionManager manager, Privilege privilege, Procedure procedure){
		Query query = manager.execute("SELECT ass FROM PrivilegeAndProcedureAssociation ass WHERE (ass.privilege.id = " + privilege.getId() + ") AND (ass.procedure.id = " + procedure.getId() + ")");
		return (PrivilegeAndProcedureAssociation)query.uniqueResult();
	}
	
	private List<PrivilegeAndProcedureAssociation> getAssociations(SessionManager manager, Privilege privilege){
			List<PrivilegeAndProcedureAssociation> result = new Vector<PrivilegeAndProcedureAssociation>();
			Query query = manager.execute("SELECT ass FROM PrivilegeAndProcedureAssociation ass WHERE ass.privilege.id = " + privilege.getId());
			for(Object object : query.list()){
				result.add((PrivilegeAndProcedureAssociation)object);
			}		
			return result;
	}
	
	private List<Long> getProcedures(SessionManager manager, Privilege privilege, Department moduleDepartment ){
//		DP : http://jira.amkai.com:8080/browse/AES-13493
		Query query = manager.execute("SELECT proc.id FROM Procedure proc WHERE proc.active = 1 AND proc.baseOrganization = :bo");
		query.setEntity("bo", moduleDepartment);		
		return query.list();
	}
}
